<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Loading Script and Style File</title>
</head>
<body>

<div id="out"></div>


<h2>Summary</h2>

<pre>
js:

  Chrome, Firefox, Safari, Opera:
    下载成功时触发 onload, 下载失败时触发 onerror
    下载成功包括 200, 302, 304 等，只要下载下来了就好
    下载失败指没下载下来，比如 404

  IE9:
    Chrome 的行为 + IE6-8 的行为

  IE6-8:
    下载成功和失败时都会触发 onreadystatechange, 无 onload / onerror
    成功和失败的含义同上

  最佳选择：
    在 Firefox, Chrome, Safari, Opera, IE9 下，用 onload + onerror
    在 IE6-8 下，用 onreadystatechange


css:

  Firefox, Chrome:
    同 js

  IE6-8:
    下载成功和失败时都会触发 onload 和 onreadystatechange, 无 onerror

  IE9:
    同 IE6-8
    onreadystatechange 会重复触发

  Opera:
    同 js
    但 css 404 时，不会触发 onerror

  Safari:
    无论下载成功还是失败，都不会触发任何事件

  最佳选择：
    非 Safari 下，用 onload + onerror
    Safari 和 Old Firefox 下，<a href="css-preload.html">css-preload.html</a>

  风险点：
    Opera 下如果 404，没有任何事件触发，有可能导致依赖该 css 的模块一直处于等待状态


测试环境：

  Chrome: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5
  Firefox: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0
  Safari: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2
  Opera: Opera/9.80 (Macintosh; Intel Mac OS X 10.7.4; U; en) Presto/2.10.289 Version/12.00

  IE9: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)
  IE6-8: 原生 IE


注意事项：请将相关文件都下载到本地的 php 环境下再测试。


最后更新时间：2012-06-27


参考文档：

  http://yuilibrary.com/projects/yui3/ticket/2530047
  http://www.zachleat.com/web/load-css-dynamically/
  http://www.backalleycoder.com/2011/03/20/link-tag-css-stylesheet-load-event/
  http://stackoverflow.com/questions/2635814/javascript-capturing-load-event-on-link
  http://yearofmoo.com/2011/03/cross-browser-stylesheet-preloading/
  http://www.cnblogs.com/rubylouvre/archive/2011/04/12/2011175.html
  
</pre>

<script>

  // test cases
  var head = document.getElementsByTagName('head')[0]
  var timestamp = new Date().getTime()

  print(navigator.userAgent)

  getScript('ok.js')
  getScript('empty.js')
  getScript('not-existed.js')
  getScript('syntax-error.js')

  getStyle('ok.css')
  getStyle('empty.css')
  getStyle('not-existed.css')
  getStyle('syntax-error.css')


  function getScript(url) {
    var s = document.createElement('script')

    s.onload = function() {
      print('script onload is fired. ' + url)
    }

    s.onerror = function() {
      print('script onerror is fired. ' + url)
    }

    s.onreadystatechange = function() {
      if (s.readyState === 'loaded' || s.readyState === 'complete') {
        print('script.readyState = ' + s.readyState + ' ' + url)
      }
    }

    s.src = url + '?' + timestamp
    head.appendChild(s)
  }


  function getStyle(url) {
    var s = document.createElement('link')
    s.rel = 'stylesheet'

    s.onload = function() {
      print('style onload is fired. ' + url)
    }

    s.onerror = function() {
      print('style onerror is fired. ' + url)
    }

    s.onreadystatechange = function() {
      if (s.readyState === 'loaded' || s.readyState === 'complete') {
        print('style.readyState = ' + s.readyState + ' ' + url)
      }
    }

    s.href = url + '?' + timestamp
    head.appendChild(s)
  }


  function print(msg) {
    var p = document.createElement('P')
    p.appendChild(document.createTextNode(msg))
    document.getElementById('out').appendChild(p)
  }

</script>
</body>
</html>
